//
//  NMDeviceInfo.m
//  podrow
//
//  Created by Michael Xu on 4/24/14.
//  Copyright (c) 2014 podrow. All rights reserved.
//

#import "NMDeviceInfo.h"
#import "AFNetworkReachabilityManager.h"
#import <SystemConfiguration/SystemConfiguration.h>

#import <AdSupport/AdSupport.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>

#import <objc/runtime.h>
#import <objc/message.h>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/sockio.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <errno.h>
#include <net/if_dl.h>
#include <ifaddrs.h>
#include <mach/machine.h>

#define BUFFERSIZE	1024
@implementation NMDeviceInfo

+(NSString *)getMAC
{
    int                 mib[6];
    size_t              len;
    char                buf[BUFFERSIZE];
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;
    
    char macAddr[64];
    
    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;
    
    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error/n");
        return FALSE;
    }
    
    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1/n");
        return FALSE;
    }
    
    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2");
        return FALSE;
    }
    
    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    
    sprintf(macAddr, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5));
    return [NSString stringWithCString:macAddr encoding:NSASCIIStringEncoding];
}

+(NSString *)getIP
{
    char wifiAddr[64];
    
    BOOL success;
    struct ifaddrs *addrs;
    const struct ifaddrs *cursor;
    
    memset(wifiAddr, 0, 64);
    
    success = getifaddrs(&addrs) == 0;
    if (success) {
        cursor = addrs;
        while(cursor != NULL) {
            // the second test keeps from picking up the loopback address
            if (cursor->ifa_addr->sa_family == AF_INET && (cursor->ifa_flags & IFF_LOOPBACK) == 0) {
                // Wi-Fi adapter
                if (strcmp(cursor->ifa_name, "en0") == 0) {
                    strcpy(wifiAddr, inet_ntoa(((struct sockaddr_in *)cursor->ifa_addr)->sin_addr));
                    break;
                }
            }
            cursor = cursor->ifa_next;
        }
        freeifaddrs(addrs);
        return [NSString stringWithCString:wifiAddr encoding:NSASCIIStringEncoding];;
    }
    
    return @"";
}

+(NSString *)getMachineDetail
{
    NSString *model = [[self class] getDeviceModel];
    
    if ([model isEqualToString:@"iPhone1,1"]) return @"iPhone 1G";
    if ([model isEqualToString:@"iPhone1,2"]) return @"iPhone 3G";
    if ([model isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS";
    if ([model isEqualToString:@"iPhone3,1"]) return @"iPhone 4 (GSM)";
    if ([model isEqualToString:@"iPhone3,2"]) return @"iPhone 4 (GSM Rev A)";
    if ([model isEqualToString:@"iPhone3,3"]) return @"iPhone 4 (CDMA)";
    if ([model isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";
    if ([model isEqualToString:@"iPhone5,1"]) return @"iPhone 5 (GSM)";
    if ([model isEqualToString:@"iPhone5,2"]) return @"iPhone 5 (GSM+CDMA)";
    if ([model isEqualToString:@"iPhone5,3"]) return @"iPhone 5c (GSM)";
    if ([model isEqualToString:@"iPhone5,4"]) return @"iPhone 5c (GSM+CDMA)";
    if ([model isEqualToString:@"iPhone6,1"]) return @"iPhone 5s (GSM)";
    if ([model isEqualToString:@"iPhone6,2"]) return @"iPhone 5s (GSM+CDMA)";
    if ([model isEqualToString:@"iPod1,1"])   return @"iPod Touch 1G";
    if ([model isEqualToString:@"iPod2,1"])   return @"iPod Touch 2G";
    if ([model isEqualToString:@"iPod3,1"])   return @"iPod Touch 3G";
    if ([model isEqualToString:@"iPod4,1"])   return @"iPod Touch 4G";
    if ([model isEqualToString:@"iPod5,1"])   return @"iPod Touch 5G";
    if ([model isEqualToString:@"iPad1,1"])   return @"iPad";
    if ([model isEqualToString:@"iPad2,1"])   return @"iPad 2 (WiFi)";
    if ([model isEqualToString:@"iPad2,2"])   return @"iPad 2 (GSM)";
    if ([model isEqualToString:@"iPad2,3"])   return @"iPad 2 (CDMA)";
    if ([model isEqualToString:@"iPad2,4"])   return @"iPad 2";
    if ([model isEqualToString:@"iPad2,5"])   return @"iPad Mini (WiFi)";
    if ([model isEqualToString:@"iPad2,6"])   return @"iPad Mini (GSM)";
    if ([model isEqualToString:@"iPad2,7"])   return @"iPad Mini (GSM+CDMA)";
    if ([model isEqualToString:@"iPad3,1"])   return @"iPad 3 (WiFi)";
    if ([model isEqualToString:@"iPad3,2"])   return @"iPad 3 (GSM+CDMA)";
    if ([model isEqualToString:@"iPad3,3"])   return @"iPad 3 (GSM)";
    if ([model isEqualToString:@"iPad3,4"])   return @"iPad 4 (WiFi)";
    if ([model isEqualToString:@"iPad3,5"])   return @"iPad 4 (GSM)";
    if ([model isEqualToString:@"iPad3,6"])   return @"iPad 4 (GSM+CDMA)";
    if ([model isEqualToString:@"iPad4,1"])   return @"iPad Air (WiFi)";
    if ([model isEqualToString:@"iPad4,2"])   return @"iPad Air (WiFi/Cellular)";
    if ([model isEqualToString:@"iPad4,4"])   return @"iPad Mini Retina (WiFi)";
    if ([model isEqualToString:@"iPad4,5"])   return @"iPad Mini Retina (WiFi/Cellular)";
    if ([model isEqualToString:@"i386"])      return @"Simulator";
    if ([model isEqualToString:@"x86_64"])    return @"Simulator";
    
    return @"Unknown";
}

+(NSString *)getDeviceModel
{
    size_t size;
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    char *machine = malloc(size);
    
    sysctlbyname("hw.machine", machine, &size, NULL, 0);
    NSString *platform = [NSString stringWithUTF8String:machine];
    free(machine);
    
    return platform;
}

+(NSString *)getCPU
{
    size_t size = 4;
    int ret;
    
    sysctlbyname("hw.cpusubtype", &ret, &size, NULL, 0);
    switch(ret)
    {
        case CPU_SUBTYPE_ARM_V4T:
            return @"ARMv4T";
            
        case CPU_SUBTYPE_ARM_V5TEJ:
            return @"ARMv5TEJ";
            
        case CPU_SUBTYPE_ARM_V6:
            return @"ARMv6";
            
        case CPU_SUBTYPE_ARM_V7:
            return @"ARMv7";
            
        case CPU_SUBTYPE_ARM_V7F:
            return @"ARMv7F";
            
        case CPU_SUBTYPE_ARM_V7K:
            return @"ARMv7K";
            
        case CPU_SUBTYPE_ARM_V7S:
            return @"ARMv7S";
            
        case 4:
            return @"X86";
            
        default:
            return @"ARM";
    }
}

+(NSString *)getCarrier
{
    CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
    CTCarrier *carrier = [networkInfo subscriberCellularProvider];
    
    // Get mobile country code
    NSString *str = [carrier mobileCountryCode];
    if(str == nil)
        str = @"";
    NSMutableString *mmc_mnc = [NSMutableString stringWithString:str];
    if([mmc_mnc length] != 0)
        [mmc_mnc appendString:@"_"];
    
    // Get mobile network code
    str = [carrier mobileNetworkCode];
    if(str == nil)
        str = @"";
    [mmc_mnc appendString:str];
    return [NSString stringWithString:mmc_mnc];;
}

+(NSString *)getIDFA
{
    return [[NSString alloc] initWithString:[[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString]];
}

+(NSString *)getOpenUDID
{
    return @"";
}

+(NSString *)getDeviceCategory
{
    UIDevice *device = [UIDevice currentDevice];
    return [[NSString alloc] initWithString:[device model]];
}

+(NSString *)getOSVersion
{
    UIDevice *device = [UIDevice currentDevice];
    return [[NSString alloc] initWithString:[device systemVersion]];
}

+(NSString *)getLanguage
{
    return [[[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"] objectAtIndex:0];
}

+(BOOL)isTrackingLimited
{
    return ![ASIdentifierManager sharedManager].advertisingTrackingEnabled;
}

+(BOOL)isJailBroken
{
    NSFileManager *sessionFileManager = [NSFileManager defaultManager];
    return [sessionFileManager fileExistsAtPath:@"/private/var/lib/apt/"];;
}

+(NSInteger)getCores
{
    return [[NSProcessInfo processInfo] processorCount];
}

+(double)getPixelScale
{
    UIScreen *screen = [UIScreen mainScreen];
    
    if([screen respondsToSelector:@selector(scale)])
        return [screen scale];
    else
        return 1.0f;
}

+(NSString *)getNetworkType
{
    __block NSString *type = @"";
    [[AFNetworkReachabilityManager sharedManager] startMonitoring];
    [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        switch (status) {
            case AFNetworkReachabilityStatusReachableViaWWAN: {
                CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
                type = networkInfo.currentRadioAccessTechnology;
            }
            
            case AFNetworkReachabilityStatusReachableViaWiFi: {
                type = @"WIFI";
                break;
            }
            case AFNetworkReachabilityStatusNotReachable:
            default:
                break;
        }
    }];
    return type;
}

+(NSString *)getEncodedDeviceToken
{
    return @"";
}

+(NSString *)getScreenSize
{
    UIScreen *screen = [UIScreen mainScreen];
    CGRect bounds = [screen bounds];
    return [[NSString alloc] initWithFormat:@"%dx%d", (int)bounds.size.width, (int)bounds.size.height];
}

+(NSString *)getBundleId
{
    return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
}

+(NSString *)getAppVersion
{
    return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
}

@end
